package com.starbooks.tmail;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;


/**
 * @author starbooks
 */
@MapperScan("com.starbooks.tmail.mapper")
@EnableCaching
@SpringBootApplication
public class TmailApplication extends WebSecurityConfigurerAdapter {

	public static void main(String[] args) {
		SpringApplication.run(TmailApplication.class, args);
	}

   @Override
   protected void configure(AuthenticationManagerBuilder auth) throws Exception {

   // 密码编码器
   PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

   // 使用内存存储
   InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> userConfig =
   auth.inMemoryAuthentication()
   // 设置密码编码器
   .passwordEncoder(passwordEncoder);

   // 注册用户admin，密码为abc,并赋予USER和ADMIN的角色权限
   userConfig.withUser("admin")
   // 可通过passwordEncoder.encode("abc")得到加密后的密码
   .password("$2a$10$5OpFvQlTIbM9Bx2pfbKVzurdQXL9zndm1SrAjEkPyIuCcZ7CqR6je")
   .authorities("ROLE_USER", "ROLE_ADMIN");

   // 注册用户myuser，密码为123456,并赋予USER的角色权限
   userConfig.withUser("user")
   // 可通过passwordEncoder.encode("123456")得到加密后的密码
   .password("$2a$10$ezW1uns4ZV63FgCLiFHJqOI6oR6jaaPYn33jNrxnkHZ.ayAFmfzLS")
   .authorities("ROLE_USER");

   }

  protected void configure1(HttpSecurity http) throws Exception {
    http
        // 访问/admin下的请求需要管理员权限
        .authorizeRequests().antMatchers("/admin/**")
        .access("hasRole('ADMIN')")
        // 通过签名后可以访问任何请求
        .and().authorizeRequests()
        .antMatchers("/**").permitAll()
        // 设置登录页和默认的跳转路径
        .and().formLogin().loginPage("/login")
        .defaultSuccessUrl("/home")
        // 登出页面和默认跳转路径
        .and().logout().logoutUrl("/logout")
        .logoutSuccessUrl("/home");
  }

	protected void configureHttpSecurity(HttpSecurity http) throws Exception {
   // 限定签名后的权限
   http.
   authorizeRequests()
   // 限定"/user/welcome"请求赋予角色ROLE_USER或者ROLE_ADMIN
   .antMatchers("/user/welcome", "/user/details").hasAnyRole("USER", "ADMIN")
   // 限定"/admin/"下所有请求权限赋予角色ROLE_ADMIN
   .antMatchers("/admin/**").hasAuthority("ROLE_ADMIN")
   // 其他路径允许签名后访问
   .anyRequest().permitAll()

   /** and代表连接词 **/
   // 对于没有配置权限的其他请求允许匿名访问
   .and().anonymous()

   // 使用Spring Security默认的登录页面
   .and().formLogin()
   // 启动HTTP基础验证
   .and().httpBasic();
		http.authorizeRequests().regexMatchers("/user/welcome", "/user/details").hasAnyRole("USER", "ADMIN")
				.regexMatchers("/admin/.*").hasAuthority("ROLE_ADMIN").and().formLogin().and().httpBasic();
		http.csrf().disable().authorizeRequests()
		// 使用Spring表达式限定只有角色ROLE_USER或者ROLE_ADMIN
		.antMatchers("/user/**").access("hasRole('USER') or hasRole('ADMIN')")
		 // 设置访问权限给角色ROLE_ADMIN，要求是完整登录(非记住我登录)
		.antMatchers("/admin/welcome1").
		    access("hasAuthority('ROLE_ADMIN') && isFullyAuthenticated()")
	    // 限定"/admin/welcome2"访问权限给角色ROLE_ADMIN，允许不完整登录
		.antMatchers("/admin/welcome2").access("hasAuthority('ROLE_ADMIN')")
		// 使用记住我的功能
		.and().rememberMe()
		// 使用Spring Security默认的登录页面
		.and().formLogin()
		// 启动HTTP基础验证
		.and().httpBasic();
	}

  // 消息队列名称

  @Value("${rabbitmq.queue.msg}")
  private String msgQueueName = null;

  @Value("${rabbitmq.queue.user}")
  private String userQueueName = null;

  @Bean
  public Queue createQueueMsg() {
    // 创建字符串消息队列，boolean值代表是否持久化消息
    return new Queue(msgQueueName, true);
  }

  @Bean
  public Queue createQueueUser() {
    // 创建用户消息队列，boolean值代表是否持久化消息
    return new Queue(userQueueName, true);
  }


}
